export abstract class Animal {
  abstract type: string;

  constructor(public name: string, public age: number) {}

  sayHello() {
    console.log(
      `各位观众, 大家好，我是${this.type}, 我叫${this.name}, 今年${this.age}`
    );
  }
}

export interface IFireShow {
  singleFire(): void;
  doubleFire(): void;
}

export interface IWisdomShow {
  suanshuit(): void;
  tiaowu(): void;
}

export class Lion extends Animal implements IFireShow {
  type: string = "狮子";

  singleFire(): void {
    console.log(`${this.name}穿越了单火圈`);
  }
  doubleFire(): void {
    console.log(`${this.name}穿越了双火圈`);
  }
}

export class Tiger extends Animal implements IFireShow {
  type: string = "老虎";

  singleFire(): void {
    console.log(`${this.name}穿越了单火圈`);
  }
  doubleFire(): void {
    console.log(`${this.name}穿越了双火圈`);
  }
}

export class Monkey extends Animal implements IWisdomShow, IFireShow {
  type: string = "猴子";
  singleFire(): void {
    console.log(`${this.name}穿越了单火圈`);
  }
  doubleFire(): void {
    console.log(`${this.name}穿越了双火圈`);
  }

  suanshuit(): void {
    console.log(`${this.name}穿越了算术题`);
  }
  tiaowu(): void {
    console.log(`${this.name}穿越了跳舞`);
  }
}

export class Dog extends Animal implements IWisdomShow {
  type: string = "狗";

  suanshuit(): void {
    console.log(`${this.name}穿越了算术题`);
  }
  tiaowu(): void {
    console.log(`${this.name}穿越了跳舞`);
  }
}

const animals: Animal[] = [
  new Lion("王富贵", 12),
  new Tiger("丧彪", 12),
  new Monkey("大圣", 22),
  new Dog("旺财", 12),
];

// 类型保护函数（在运行中检查）, 该函数必须返回boolean
function hasFireShow(animal: object): animal is IFireShow {
  if ((animal as IFireShow).singleFire && (animal as IFireShow).doubleFire) {
    return true;
  }
  return false;
}

function hasWisdomShow(animal: object): animal is IWisdomShow {
  if ((animal as IWisdomShow).suanshuit && (animal as IWisdomShow).tiaowu) {
    return true;
  }

  return false;
}

animals.forEach((animal) => {
  animal.sayHello();

  // java中判断, js不行（在ts中接口会被移除）
  // if(animal instanceof IFireShow)
  if (hasFireShow(animal)) {
    animal.singleFire();
    animal.doubleFire();
  }

  if (hasWisdomShow(animal)) {
    animal.suanshuit();
    animal.tiaowu();
  }
});

// 接口可以继承类
class A {
  a1: string = "";
  a2: string = "";
  a3: string = "";
}

class B {
  b1: number = 0;
  b2: number = 1;
  b3: number = 2;
}

interface C extends A, B {}

const c: C = {
  a1: "",
  a2: "",
  a3: "",
  b1: 0,
  b2: 0,
  b3: 0,
};

export {};
